using System;
using System.Collections.Generic;
using System.Reflection;

namespace Universe.OneC.DomainModel
{
    public class MetaProperty
    {
        private FieldInfo accessor;
        public bool AllowsNULL;
        public bool CanBeNegative;
        public readonly Universe.OneC.DomainModel.MetaClass Class;
        public Universe.OneC.DomainModel.DatePart DatePart;
        public Universe.OneC.DomainModel.MetaField fBinary;
        public Universe.OneC.DomainModel.MetaField fBoolean;
        public Universe.OneC.DomainModel.MetaField fDateTime;
        public Universe.OneC.DomainModel.MetaField fDiscriminator;
        public Universe.OneC.DomainModel.MetaField fIdentity;
        public Universe.OneC.DomainModel.MetaField fNumeric;
        public Universe.OneC.DomainModel.MetaField fReference;
        public Universe.OneC.DomainModel.MetaField fString;
        public Universe.OneC.DomainModel.MetaField fVersion;
        public bool HasFixedLength;
        public bool IsUnique;
        public string Name;
        public string Synonym;
        public List<string> Names;
        public Periodicity Periodicity;
        public int Precision;
        public Universe.OneC.DomainModel.DataPurpose Purpose;
        public int Scale;
        public int Size;
        public string Storage;
        public string TypeName;
        public List<Type> Types;
        public Type ValueType;

        public MetaProperty(Universe.OneC.DomainModel.MetaClass owner, string name)
        {
            this.Class = owner;
            this.Name = name;
        }

        public List<Universe.OneC.DomainModel.MetaField> GetFields()
        {
            List<Universe.OneC.DomainModel.MetaField> list = new List<Universe.OneC.DomainModel.MetaField>();
            if (this.fIdentity != null)
            {
                list.Add(this.fIdentity);
            }
            if (this.fVersion != null)
            {
                list.Add(this.fVersion);
            }
            if (this.fDiscriminator != null)
            {
                list.Add(this.fDiscriminator);
            }
            if (this.fBinary != null)
            {
                list.Add(this.fBinary);
            }
            if (this.fBoolean != null)
            {
                list.Add(this.fBoolean);
            }
            if (this.fNumeric != null)
            {
                list.Add(this.fNumeric);
            }
            if (this.fString != null)
            {
                list.Add(this.fString);
            }
            if (this.fDateTime != null)
            {
                list.Add(this.fDateTime);
            }
            if (this.fReference != null)
            {
                list.Add(this.fReference);
            }
            return list;
        }

        public object GetValue(object target)
        {
            if (this.accessor == null)
            {
                this.accessor = this.Class.Type.GetField(this.Storage, BindingFlags.NonPublic | BindingFlags.Instance);
            }
            if (this.accessor == null)
            {
                return null;
            }
            return this.accessor.GetValue(target);
        }

        public void SetValue(object target, object value)
        {
            if (this.accessor == null)
            {
                this.accessor = this.Class.Type.GetField(this.Storage, BindingFlags.NonPublic | BindingFlags.Instance);
            }
            this.accessor.SetValue(target, value);
        }

        public Universe.OneC.DomainModel.MetaField ValueHolder
        {
            get
            {
                if ((this.Purpose & Universe.OneC.DomainModel.DataPurpose.Identity) == Universe.OneC.DomainModel.DataPurpose.Identity)
                {
                    return this.fIdentity;
                }
                if ((this.Purpose & Universe.OneC.DomainModel.DataPurpose.Version) == Universe.OneC.DomainModel.DataPurpose.Version)
                {
                    return this.fVersion;
                }
                if ((this.Purpose & Universe.OneC.DomainModel.DataPurpose.Primitive) == Universe.OneC.DomainModel.DataPurpose.Primitive)
                {
                    Type type = this.Types[0];
                    if (type == typeof(bool))
                    {
                        return this.fBoolean;
                    }
                    if (type == typeof(string))
                    {
                        return this.fString;
                    }
                    if (type == typeof(DateTime))
                    {
                        return this.fDateTime;
                    }
                    if (type == typeof(byte[]))
                    {
                        return this.fBinary;
                    }
                    return this.fNumeric;
                }
                if ((this.Purpose & Universe.OneC.DomainModel.DataPurpose.Reference) == Universe.OneC.DomainModel.DataPurpose.Reference)
                {
                    return this.fReference;
                }
                return null;
            }
        }
    }
}